﻿using System;
using FluentValidation.TestHelper;
using GiveAQuiz.Data;
using GiveAQuiz.Web.Models;
using GiveAQuiz.Web.Validation;
using Moq;
using NUnit.Framework;

namespace GiveAQuiz.Web.Tests.Validation
{
  [TestFixture]
  public class QuizPickerValidatorTest
  {
    private Mock<IQuizRepository> MockRepository
    {
      get; set;
    }

    private QuizPickerValidator Validator
    {
      get; set;
    }

    [TestFixtureSetUp]
    public void SetUpRepository()
    {
      MockRepository = new Mock<IQuizRepository>();
      Validator = new QuizPickerValidator(MockRepository.Object);
    }

    [Test]
    public void RuleFor_QuizPassphrase_should_not_have_error_if_found_in_repository()
    {
      var model = new QuizPickerViewModel { QuizPassphrase = "12345" };

      MockRepository.Setup(r => r.GetQuizByPassphrase(model.QuizPassphrase)).Returns(new Quiz()).Verifiable();
     
      Validator.ShouldNotHaveValidationErrorFor(qp => qp.QuizPassphrase, model);

      MockRepository.VerifyAll();
    }

    [Test]
    public void RuleFor_QuizPassphrase_should_not_be_null()
    {
      var model = new QuizPickerViewModel {QuizPassphrase = null};
      Validator.ShouldHaveValidationErrorFor(qp => qp.QuizPassphrase, model);
    }

    [Test]
    public void RuleFor_QuizPassphrase_should_not_be_blank()
    {
      var model = new QuizPickerViewModel { QuizPassphrase = " "};
      Validator.ShouldHaveValidationErrorFor(qp => qp.QuizPassphrase, model);
    }

    [Test]
    public void RuleFor_QuizPassphrase_should_not_have_error_if_not_found_in_repository()
    {
      var model = new QuizPickerViewModel { QuizPassphrase = "12345" };

      MockRepository.Setup(r => r.GetQuizByPassphrase(model.QuizPassphrase)).Returns(null as Quiz).Verifiable();

      Validator.ShouldHaveValidationErrorFor(qp => qp.QuizPassphrase, model);

      MockRepository.VerifyAll();
    }

    [Test]
    public void Validate_TakerName_is_null_should_not_have_error_if_quiz_passphrase_is_null()
    {
      var model = new QuizPickerViewModel { QuizPassphrase = null, TakerName = null };
      
      Validator.ShouldHaveValidationErrorFor(qp => qp.QuizPassphrase, model);
      Validator.ShouldNotHaveValidationErrorFor(qp => qp.TakerName, model);
    }

    [Test]
    public void Validator_TakerName_is_null_should_not_have_error_if_not_found_in_repository()
    {
      var model = new QuizPickerViewModel { QuizPassphrase = "12345" };

      MockRepository.Setup(r => r.GetQuizByPassphrase(model.QuizPassphrase)).Returns(null as Quiz).Verifiable();

      Validator.ShouldHaveValidationErrorFor(qp => qp.QuizPassphrase, model);
      Validator.ShouldNotHaveValidationErrorFor(qp => qp.TakerName, model);

      MockRepository.VerifyAll();
    }

    [Test]
    public void Validator_TakerName_is_null_should_not_have_error_if_IsNameOptional_is_true()
    {
      var model = new QuizPickerViewModel { QuizPassphrase = "12345" };

      MockRepository.Setup(r => r.GetQuizByPassphrase(model.QuizPassphrase)).Returns(new Quiz { IsNameOptional = true}).Verifiable();

      Validator.ShouldNotHaveValidationErrorFor(qp => qp.QuizPassphrase, model);
      Validator.ShouldNotHaveValidationErrorFor(qp => qp.TakerName, model);

      MockRepository.VerifyAll();
    }

    [Test]
    public void Validator_TakerName_is_null_should_have_error_if_IsNameOptional_is_false()
    {
      var model = new QuizPickerViewModel { QuizPassphrase = "12345" };

      MockRepository.Setup(r => r.GetQuizByPassphrase(model.QuizPassphrase)).Returns(new Quiz { IsNameOptional = false }).Verifiable();

      Validator.ShouldNotHaveValidationErrorFor(qp => qp.QuizPassphrase, model);
      Validator.ShouldHaveValidationErrorFor(qp => qp.TakerName, model);

      MockRepository.VerifyAll();
    }

    [Test]
    public void Validate_TakerName_is_empty_should_not_have_error_if_quiz_passphrase_is_null()
    {
      var model = new QuizPickerViewModel { QuizPassphrase = "12345", TakerName = String.Empty };

      Validator.ShouldHaveValidationErrorFor(qp => qp.QuizPassphrase, model);
      Validator.ShouldNotHaveValidationErrorFor(qp => qp.TakerName, model);
    }

    [Test]
    public void Validator_TakerName_is_empty_should_not_have_error_if_not_found_in_repository()
    {
      var model = new QuizPickerViewModel { QuizPassphrase = "12345", TakerName = String.Empty };

      MockRepository.Setup(r => r.GetQuizByPassphrase(model.QuizPassphrase)).Returns(null as Quiz).Verifiable();

      Validator.ShouldHaveValidationErrorFor(qp => qp.QuizPassphrase, model);
      Validator.ShouldNotHaveValidationErrorFor(qp => qp.TakerName, model);

      MockRepository.VerifyAll();
    }

    [Test]
    public void Validator_TakerName_is_empty_should_not_have_error_if_IsNameOptional_is_true()
    {
      var model = new QuizPickerViewModel { QuizPassphrase = "12345", TakerName = String.Empty };

      MockRepository.Setup(r => r.GetQuizByPassphrase(model.QuizPassphrase)).Returns(new Quiz { IsNameOptional = true }).Verifiable();

      Validator.ShouldNotHaveValidationErrorFor(qp => qp.QuizPassphrase, model);
      Validator.ShouldNotHaveValidationErrorFor(qp => qp.TakerName, model);

      MockRepository.VerifyAll();
    }

    [Test]
    public void Validator_TakerName_is_empty_should_have_error_if_IsNameOptional_is_false()
    {
      var model = new QuizPickerViewModel { QuizPassphrase = "12345", TakerName = String.Empty };

      MockRepository.Setup(r => r.GetQuizByPassphrase(model.QuizPassphrase)).Returns(new Quiz { IsNameOptional = false }).Verifiable();

      Validator.ShouldNotHaveValidationErrorFor(qp => qp.QuizPassphrase, model);
      Validator.ShouldHaveValidationErrorFor(qp => qp.TakerName, model);

      MockRepository.VerifyAll();
    }

  }
}
